// 对象类使用示例 - zh-object.js
// 支持 CommonJS 和 ES 模块导入
const mathModule = require('../../zh/公共函数/zh-object.js');
const { 对象 } = mathModule || {
  对象: mathModule.对象 || mathModule.default?.对象
};

console.log('=== 对象类 (zh-object.js) 使用示例 ===\n');

// 1. 基本对象创建与获取
console.log('1. 基本对象创建与获取');

// 创建空对象
const 空对象 = new 对象();
console.log('空对象:', 空对象.取值());

// 从现有对象创建
const 用户对象 = new 对象({ 姓名: '张三', 年龄: 25, 城市: '北京' });
console.log('用户对象:', 用户对象.取值());

// 打印对象
用户对象.打印();

// 2. 对象属性访问与遍历
console.log('\n2. 对象属性访问与遍历');

// 获取键名
console.log('所有键名:', 用户对象.取键());

// 获取值列表
console.log('所有值:', 用户对象.取值列表());

// 获取键值对
console.log('所有键值对:', 用户对象.取条目());

// 检查属性是否存在
console.log('是否有"姓名"属性:', 用户对象.是否自有属性('姓名'));
console.log('是否有"邮箱"属性:', 用户对象.是否自有属性('邮箱'));

// 3. 对象属性管理
console.log('\n3. 对象属性管理');

// 定义属性描述符
const 描述符对象 = {
  可枚举: false,
  可写: false,
  值: 'private-value'
};
const 新对象 = 用户对象.定义属性('私有属性', 描述符对象);
console.log('添加私有属性后:', 新对象.取值());
console.log('私有属性是否可枚举:', '私有属性' in 新对象.取值());

// 删除属性
const 删除后对象 = 新对象.删除属性('城市');
console.log('删除"城市"属性后:', 删除后对象.取值());

// 4. 对象合并与复制
console.log('\n4. 对象合并与复制');

// 合并对象
const 个人信息 = { 身高: 180, 体重: 75 };
const 合并结果 = 用户对象.合并(个人信息);
console.log('合并个人信息后:', 合并结果.取值());

// 克隆对象
const 克隆对象 = 用户对象.克隆();
console.log('克隆对象:', 克隆对象.取值());
console.log('是否为相同引用:', 用户对象.取值() === 克隆对象.取值());

// 深度克隆
const 复杂对象 = new 对象({ 基本信息: { 姓名: '李四', 年龄: 30 }, 爱好: ['读书', '游泳'] });
const 深拷贝 = 复杂对象.取深拷贝();
// 修改原始对象的嵌套属性
复杂对象.设路径值('基本信息.年龄', 31);
console.log('修改原始对象后，深拷贝的年龄:', 深拷贝.取路径值('基本信息.年龄'));

// 5. 对象不可变性操作
console.log('\n5. 对象不可变性操作');

// 冻结对象
const 冻结对象 = 用户对象.冻结();
try {
  const 尝试修改 = 冻结对象._值; // 获取内部对象进行修改测试
  尝试修改.年龄 = 30;
  console.log('冻结后，修改内部引用:', 冻结对象.取值());
} catch (e) {
  console.log('冻结对象错误:', e.message);
}

// 密封对象
const 密封对象 = 用户对象.密封();
try {
  const 尝试添加 = 密封对象._值; // 获取内部对象进行添加测试
  尝试添加.邮箱 = 'sealed@example.com';
  console.log('密封后，尝试添加属性:', 密封对象.取值());
} catch (e) {
  console.log('密封对象错误:', e.message);
}

// 检查可扩展性
console.log('原始对象是否可扩展:', 用户对象.判断可扩展());
console.log('冻结对象是否冻结:', 冻结对象.判断冻结());

// 6. 对象映射与过滤
console.log('\n6. 对象映射与过滤');

// 映射对象值
const 映射结果 = 用户对象.映射值((值, 键) => {
  if (键 === '年龄') return 值 + 1;
  return 值;
});
console.log('映射后年龄加1:', 映射结果.取值());

// 过滤对象键
const 过滤结果 = 用户对象.过滤键((键, 值) => {
  return typeof 值 === 'string';
});
console.log('只保留字符串值的属性:', 过滤结果.取值());

// 7. 对象序列化
console.log('\n7. 对象序列化');

// 转换为JSON字符串
console.log('JSON字符串(缩进2):', 用户对象.转JSON());
console.log('JSON字符串(无缩进):', 用户对象.转JSON(0));

// 转换为普通字符串
console.log('对象字符串表示:', 用户对象.转字符串());

// 8. 嵌套属性操作
console.log('\n8. 嵌套属性操作');

// 创建嵌套对象
const 配置对象 = new 对象({
  数据库: {
    主机: 'localhost',
    端口: 3306,
    认证: {
      用户名: 'root',
      密码: 'password'
    }
  },
  应用: {
    版本: '1.0.0'
  }
});

// 获取嵌套属性值
console.log('数据库主机:', 配置对象.取路径值('数据库.主机'));
console.log('认证用户名:', 配置对象.取路径值('数据库.认证.用户名'));
console.log('不存在的路径:', 配置对象.取路径值('数据库.连接池'));

// 设置嵌套属性值
const 新配置 = 配置对象.设路径值('数据库.端口', 5432);
console.log('更新端口后:', 新配置.取路径值('数据库.端口'));

// 创建新的嵌套路径
const 扩展配置 = 新配置.设路径值('日志.级别', 'info');
console.log('新添加的日志配置:', 扩展配置.取路径值('日志'));

// 9. 静态方法使用示例
console.log('\n9. 静态方法使用示例');

// 判断是否为对象
console.log('{} 是否为对象:', 对象.是否对象({}));
console.log('[] 是否为对象:', 对象.是否对象([]));
console.log('null 是否为对象:', 对象.是否对象(null));
console.log('"字符串" 是否为对象:', 对象.是否对象('字符串'));

// 从键值对创建对象
const 键值对 = [['姓名', '王五'], ['年龄', 28], ['城市', '上海']];
const 条目对象 = 对象.从条目(键值对);
console.log('从键值对创建对象:', 条目对象.取值());

// 创建带有原型的对象
const 原型对象 = { 打招呼: function() { return `你好，我是${this.姓名}`; } };
const 带原型对象 = 对象.创建(原型对象);
const 完整对象 = 带原型对象.合并({ 姓名: '原型用户' });
// 由于原型方法不能直接通过取值()访问，这里做特殊处理
const 临时对象 = 完整对象.取值();
Object.setPrototypeOf(临时对象, 原型对象);
console.log('原型方法调用:', 临时对象.打招呼());

// 获取对象所有键名（静态方法）
console.log('静态方法获取键名:', 对象.键({ a: 1, b: 2, c: 3 }));
console.log('静态方法获取值:', 对象.值({ a: 1, b: 2, c: 3 }));
console.log('静态方法获取条目:', 对象.条目({ a: 1, b: 2, c: 3 }));

// 10. 链式调用示例
console.log('\n10. 链式调用示例');

const 链式操作 = new 对象()
  .合并({ id: 1, 状态: '活跃' })
  .合并({ 标签: ['重要', '紧急'] })
  .设路径值('详情.创建时间', new Date().toISOString())
  .映射值((值, 键) => {
    if (键 === 'id') return 值 + 1000;
    return 值;
  });

console.log('链式调用结果:', 链式操作.取值());

// 11. 实际应用场景 - 配置管理
console.log('\n11. 实际应用场景 - 配置管理');

class 配置管理器 {
  constructor(默认配置 = {}) {
    this.配置 = new 对象(默认配置);
  }
  
  加载用户配置(用户配置) {
    this.配置 = this.配置.合并(用户配置);
    return this;
  }
  
  获取配置项(路径, 默认值) {
    if (路径) {
      return this.配置.取路径值(路径, 默认值);
    }
    return this.配置.取值();
  }
  
  设置配置项(路径, 值) {
    this.配置 = this.配置.设路径值(路径, 值);
    return this;
  }
  
  保存为JSON() {
    return this.配置.转JSON(2);
  }
}

// 使用配置管理器
const 应用配置 = new 配置管理器({
  服务器: {
    端口: 8000,
    主机: 'localhost',
    超时: 3000
  },
  数据库: {
    类型: 'mysql',
    连接数: 10
  },
  日志: {
    级别: 'info',
    路径: './logs'
  }
});

应用配置
  .加载用户配置({
    服务器: { 端口: 8080 },
    数据库: { 连接数: 20 }
  })
  .设置配置项('日志.级别', 'debug')
  .设置配置项('特性.新版本', true);

console.log('端口配置:', 应用配置.获取配置项('服务器.端口'));
console.log('日志级别:', 应用配置.获取配置项('日志.级别'));
console.log('不存在配置的默认值:', 应用配置.获取配置项('缓存.大小', 1024));
console.log('配置JSON字符串:', 应用配置.保存为JSON());

// 12. 实际应用场景 - 数据转换
console.log('\n12. 实际应用场景 - 数据转换');

function 转换用户数据(原始数据) {
  return new 对象(原始数据)
    // 重命名字段
    .映射值((值, 键) => {
      const 映射 = {
        'userName': '用户名',
        'userAge': '年龄',
        'userAddress': '地址'
      };
      return 映射[键] || 键;
    })
    // 过滤敏感信息
    .过滤键((键, 值) => !['password', 'token'].includes(键))
    // 添加元数据
    .合并({ 处理时间: new Date().toISOString() })
    .取值();
}

const API数据 = {
  userName: 'testuser',
  userAge: 30,
  userAddress: '北京市朝阳区',
  password: 'hashed-password',
  token: 'jwt-token-123'
};

const 转换后数据 = 转换用户数据(API数据);
console.log('API数据转换结果:', 转换后数据);

// 13. 实际应用场景 - 表单数据处理
console.log('\n13. 实际应用场景 - 表单数据处理');

function 验证并处理表单(表单数据) {
  // 创建表单数据对象
  const 表单 = new 对象(表单数据);
  const 错误 = [];
  
  // 验证必填字段
  const 必填字段 = ['姓名', '邮箱', '手机号'];
  必填字段.forEach(字段 => {
    if (!表单.取路径值(字段)) {
      错误.push(`字段"${字段}"不能为空`);
    }
  });
  
  // 验证邮箱格式
  const 邮箱 = 表单.取路径值('邮箱');
  if (邮箱 && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(邮箱)) {
    错误.push('邮箱格式不正确');
  }
  
  // 验证手机号格式
  const 手机号 = 表单.取路径值('手机号');
  if (手机号 && !/^1[3-9]\d{9}$/.test(手机号)) {
    错误.push('手机号格式不正确');
  }
  
  // 如果有错误，返回错误信息
  if (错误.length > 0) {
    return { 成功: false, 错误 };
  }
  
  // 处理数据（例如，格式化）
  const 处理后数据 = 表单
    .映射值((值, 键) => {
      if (typeof 值 === 'string') return 值.trim();
      return 值;
    })
    .合并({ 提交时间: new Date().toISOString(), 状态: '待审核' })
    .取值();
  
  return { 成功: true, 数据: 处理后数据 };
}

// 测试表单处理
const 有效表单 = {
  姓名: '  张三  ',
  邮箱: 'zhangsan@example.com',
  手机号: '13800138000',
  备注: '无'
};

const 无效表单 = {
  姓名: '李四',
  邮箱: 'invalid-email',
  手机号: '12345'
};

// 使用JSON.stringify确保对象正确格式化输出
console.log('有效表单处理结果:', JSON.stringify(验证并处理表单(有效表单), null, 2));
console.log('无效表单处理结果:', JSON.stringify(验证并处理表单(无效表单), null, 2));

// 14. 性能优化 - 对象属性操作对比
console.log('\n14. 性能优化 - 对象属性操作对比');

function 性能测试() {
  // 创建测试数据
  const 测试对象 = {};
  for (let i = 0; i < 1000; i++) {
    测试对象[`属性${i}`] = i;
  }
  
  // 测试直接操作
  console.time('原生对象属性访问');
  let 原生计数 = 0;
  for (let i = 0; i < 1000; i++) {
    原生计数 += 测试对象[`属性${i}`];
  }
  console.timeEnd('原生对象属性访问');
  
  // 测试对象类操作
  const 对象实例 = new 对象(测试对象);
  console.time('对象类属性访问');
  let 对象计数 = 0;
  for (let i = 0; i < 1000; i++) {
    对象计数 += 对象实例.取值()[`属性${i}`];
  }
  console.timeEnd('对象类属性访问');
  
  console.log('两种方法结果一致:', 原生计数 === 对象计数);
}

性能测试();

console.log('\n=== 所有示例执行完毕 ===');
